{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Indexing / querying JSON documents\n",
    "## Adding a JSON document to an index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'OK'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import redis\n",
    "from redis.commands.json.path import Path\n",
    "import redis.commands.search.aggregation as aggregations\n",
    "import redis.commands.search.reducers as reducers\n",
    "from redis.commands.search.field import TextField, NumericField, TagField\n",
    "from redis.commands.search.index_definition import IndexDefinition, IndexType\n",
    "from redis.commands.search.query import NumericFilter, Query\n",
    "\n",
    "\n",
    "r = redis.Redis(host='localhost', port=6379)\n",
    "user1 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Paul John\",\n",
    "        \"email\": \"paul.john@example.com\",\n",
    "        \"age\": 42,\n",
    "        \"city\": \"London\"\n",
    "    }\n",
    "}\n",
    "user2 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Eden Zamir\",\n",
    "        \"email\": \"eden.zamir@example.com\",\n",
    "        \"age\": 29,\n",
    "        \"city\": \"Tel Aviv\"\n",
    "    }\n",
    "}\n",
    "user3 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Paul Zamir\",\n",
    "        \"email\": \"paul.zamir@example.com\",\n",
    "        \"age\": 35,\n",
    "        \"city\": \"Tel Aviv\"\n",
    "    }\n",
    "}\n",
    "\n",
    "user4 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Sarah Zamir\",\n",
    "        \"email\": \"sarah.zamir@example.com\",\n",
    "        \"age\": 30,\n",
    "        \"city\": \"Paris\"\n",
    "    }\n",
    "}\n",
    "r.json().set(\"user:1\", Path.root_path(), user1)\n",
    "r.json().set(\"user:2\", Path.root_path(), user2)\n",
    "r.json().set(\"user:3\", Path.root_path(), user3)\n",
    "r.json().set(\"user:4\", Path.root_path(), user4)\n",
    "\n",
    "schema = (TextField(\"$.user.name\", as_name=\"name\"),TagField(\"$.user.city\", as_name=\"city\"), NumericField(\"$.user.age\", as_name=\"age\"))\n",
    "r.ft().create_index(schema, definition=IndexDefinition(prefix=[\"user:\"], index_type=IndexType.JSON))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Searching"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simple search"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Result{2 total, docs: [Document {'id': 'user:1', 'payload': None, 'json': '{\"user\":{\"name\":\"Paul John\",\"email\":\"paul.john@example.com\",\"age\":42,\"city\":\"London\"}}'}, Document {'id': 'user:3', 'payload': None, 'json': '{\"user\":{\"name\":\"Paul Zamir\",\"email\":\"paul.zamir@example.com\",\"age\":35,\"city\":\"Tel Aviv\"}}'}]}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.ft().search(\"Paul\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Filtering search results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Result{1 total, docs: [Document {'id': 'user:3', 'payload': None, 'json': '{\"user\":{\"name\":\"Paul Zamir\",\"email\":\"paul.zamir@example.com\",\"age\":35,\"city\":\"Tel Aviv\"}}'}]}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q1 = Query(\"Paul\").add_filter(NumericFilter(\"age\", 30, 40))\n",
    "r.ft().search(q1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Paginating and Ordering search Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Result{4 total, docs: [Document {'id': 'user:1', 'payload': None, 'age': '42', 'json': '{\"user\":{\"name\":\"Paul John\",\"email\":\"paul.john@example.com\",\"age\":42,\"city\":\"London\"}}'}, Document {'id': 'user:3', 'payload': None, 'age': '35', 'json': '{\"user\":{\"name\":\"Paul Zamir\",\"email\":\"paul.zamir@example.com\",\"age\":35,\"city\":\"Tel Aviv\"}}'}]}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Search for all users, returning 2 users at a time and sorting by age in descending order\n",
    "offset = 0\n",
    "num = 2\n",
    "q = Query(\"*\").paging(offset, num).sort_by(\"age\", asc=False) # pass asc=True to sort in ascending order\n",
    "r.ft().search(q)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Counting the total number of Items"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q = Query(\"*\").paging(0, 0)\n",
    "r.ft().search(q).total"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Projecting using JSON Path expressions "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document {'id': 'user:1', 'payload': None, 'city': 'London'},\n",
       " Document {'id': 'user:3', 'payload': None, 'city': 'Tel Aviv'}]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.ft().search(Query(\"Paul\").return_field(\"$.user.city\", as_field=\"city\")).docs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Aggregation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[b'age', b'35'], [b'age', b'42']]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "req = aggregations.AggregateRequest(\"Paul\").sort_by(\"@age\")\n",
    "r.ft().aggregate(req).rows"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Count the total number of Items"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[b'total', b'4']]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The group_by expects a string or list of strings to group the results before applying the aggregation function to\n",
    "# each group. Passing an empty list here acts as `GROUPBY 0` which applies the aggregation function to the whole results\n",
    "req = aggregations.AggregateRequest(\"*\").group_by([], reducers.count().alias(\"total\"))\n",
    "r.ft().aggregate(req).rows"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "d45c99ba0feda92868abafa8257cbb4709c97f1a0b5dc62bbeebdf89d4fad7fe"
  },
  "kernelspec": {
   "display_name": "redis-py",
   "language": "python",
   "name": "redis-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
